package base.thread_example.example06;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.locks.LockSupport;

/**
 * t1线程输出a， t2线程输出b， t3线程输出c，最终输出格式是：循环abc
 *
 * 采用 LockSupport 的 park、unpark方式
 *
 * 这种方式是这样的: t1,t2,t3去执行 Task.print(),进入就被关卡 LockSupport.park()全部阻止,
 * 等 main 线程去把t1关卡拿掉后,t1就接着执行 Task.print()剩余逻辑,并在执行完 print()逻辑后,又会主动给t1挂上关卡,
 * 但在给t1主动挂上关卡前,又通过 LockSupport.unpark(next) 将next线程关卡拿掉了,这样接着next就可以运行剩余 print()逻辑
 */
public class ParkUnpark {
    private static final Logger log = LoggerFactory.getLogger(ParkUnpark.class);

    static Thread t1;
    static Thread t2;
    static Thread t3;

    public static void main(String[] args) {
        Task t = new Task();

        t1 = new Thread(()->{
            while (true){
                t.print("a", t2);
            }
        },"t1");

        t2 = new Thread(()->{
            while (true){
                t.print("b", t3);
            }
        },"t2");

        t3 = new Thread(()->{
            while (true){
                t.print("c", t1);
            }
        },"t3");

        t1.start();
        t2.start();
        t3.start();

        log.info("{} 开始唤醒 t1", Thread.currentThread().getName());
        LockSupport.unpark(t1);
    }


}

class Task {
    private static final Logger log = LoggerFactory.getLogger(Task.class);

    public void print(String s, Thread next) {
        LockSupport.park();//当前线程执行任务执行到这句就暂停当前线程,等待被唤醒
        log.info("{}:{}", Thread.currentThread().getName(), s);
        LockSupport.unpark(next);
    }
}
